using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using SheLife.Domain.Entities;
using SheLife.Domain.Interfaces;

namespace SheLife.Infrastructure.Repositories
{
    public class HabitRecordRepository : IHabitRecordRepository
    {
        private readonly SheLifeDbContext _context;

        public HabitRecordRepository(SheLifeDbContext context)
        {
            _context = context;
        }

        public async Task<HabitRecord> GetByIdAsync(int id)
        {
            return await _context.HabitRecords.FindAsync(id);
        }

        public async Task<IEnumerable<HabitRecord>> GetByHabitIdAsync(int habitId)
        {
            return await _context.HabitRecords
                .Where(r => r.HabitId == habitId)
                .OrderByDescending(r => r.Date)
                .ToListAsync();
        }

        public async Task<IEnumerable<HabitRecord>> GetByUserIdAsync(int userId)
        {
            return await _context.HabitRecords
                .Include(r => r.Habit)
                .Where(r => r.Habit.UserId == userId)
                .OrderByDescending(r => r.Date)
                .ToListAsync();
        }

        public async Task<IEnumerable<HabitRecord>> GetByUserIdAndDateRangeAsync(int userId, DateTime startDate, DateTime endDate)
        {
            return await _context.HabitRecords
                .Include(r => r.Habit)
                .Where(r => r.Habit.UserId == userId && 
                           r.Date >= startDate && 
                           r.Date <= endDate)
                .OrderByDescending(r => r.Date)
                .ToListAsync();
        }

        public async Task<HabitRecord> GetByHabitIdAndDateAsync(int habitId, DateTime date)
        {
            return await _context.HabitRecords
                .FirstOrDefaultAsync(r => r.HabitId == habitId && r.Date == date);
        }

        public async Task<HabitRecord> AddAsync(HabitRecord record)
        {
            record.CreatedAt = DateTime.UtcNow;
            await _context.HabitRecords.AddAsync(record);
            await _context.SaveChangesAsync();
            return record;
        }

        public async Task UpdateAsync(HabitRecord record)
        {
            record.UpdatedAt = DateTime.UtcNow;
            _context.Entry(record).State = EntityState.Modified;
            await _context.SaveChangesAsync();
        }

        public async Task DeleteAsync(int id)
        {
            var record = await GetByIdAsync(id);
            if (record != null)
            {
                _context.HabitRecords.Remove(record);
                await _context.SaveChangesAsync();
            }
        }

        public async Task<bool> ExistsAsync(int id)
        {
            return await _context.HabitRecords.AnyAsync(r => r.Id == id);
        }

        public async Task<bool> ExistsByHabitIdAndDateAsync(int habitId, DateTime date)
        {
            return await _context.HabitRecords.AnyAsync(r => r.HabitId == habitId && r.Date == date);
        }

        public async Task<int> GetCompletionCountAsync(int habitId, DateTime startDate, DateTime endDate)
        {
            return await _context.HabitRecords
                .CountAsync(r => r.HabitId == habitId && 
                               r.Date >= startDate && 
                               r.Date <= endDate);
        }

        public async Task<Dictionary<DateTime, int>> GetMonthlyCompletionStatsAsync(int userId, int year, int month)
        {
            var startDate = new DateTime(year, month, 1);
            var endDate = startDate.AddMonths(1).AddDays(-1);

            var records = await _context.HabitRecords
                .Include(r => r.Habit)
                .Where(r => r.Habit.UserId == userId && 
                           r.Date >= startDate && 
                           r.Date <= endDate)
                .GroupBy(r => r.Date)
                .Select(g => new { Date = g.Key, Count = g.Count() })
                .ToListAsync();

            return records.ToDictionary(r => r.Date, r => r.Count);
        }
    }
}